use std::time::Duration;

use base_data::channel::CommandMsg;
use bytes::Bytes;
use tools::{utils::gen_id::get_now_duration, ResultEx, ResultNull};
use tracing::error;

use super::{dialog::Dialog, sipdata::SipData, MAX_TRY_TIME, T1,};

pub(crate) mod inv_client;
pub(crate) mod inv_server;
pub(crate) mod no_tran;
pub(crate) mod non_inv_client;
pub(crate) mod non_inv_server;

///Sip事务描述.
///
/// 不保存数据.仅描述事务本身.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum SipTransaction {
	InviteClient,
	NonInviteClient,
	InviteServer,
	NonInviteServer,
	NoN,
}

impl SipTransaction {
	/// 事务开始初始化方法
	/// 返回需要超时的时间和超时控制.
	pub fn start_tran(&self, dialog: &mut Dialog) {
		match self {
			SipTransaction::InviteClient => inv_client::start_tran(dialog),
			SipTransaction::NonInviteClient => non_inv_client::start_tran(dialog),
			SipTransaction::InviteServer => inv_server::start_tran(dialog),
			SipTransaction::NonInviteServer => non_inv_server::start_tran(dialog),
			SipTransaction::NoN => no_tran::start_tran(dialog),
		}
	}
	///处理事务收到的传输层的消息
	pub fn handle_tran_msg(&self, dialog: &mut Dialog, sip_data: SipData) -> ResultNull {
		match self {
			SipTransaction::InviteClient => inv_client::handle_tran_msg(dialog, sip_data),
			SipTransaction::NonInviteClient => non_inv_client::handle_tran_msg(dialog, sip_data),
			SipTransaction::InviteServer => inv_server::handle_tran_msg(dialog, sip_data),
			SipTransaction::NonInviteServer => non_inv_server::handle_tran_msg(dialog, sip_data),
			SipTransaction::NoN => no_tran::handle_tran_msg(dialog, sip_data),
		}
	}
	///处理事务收到的命令消息
	pub fn handle_command_msg(&self, dialog: &mut Dialog, cmd_msg: CommandMsg) -> ResultNull {
		match self {
			SipTransaction::InviteClient => inv_client::handle_command_msg(dialog, cmd_msg),
			SipTransaction::NonInviteClient => non_inv_client::handle_command_msg(dialog, cmd_msg),
			SipTransaction::InviteServer => inv_server::handle_command_msg(dialog, cmd_msg),
			SipTransaction::NonInviteServer => non_inv_server::handle_command_msg(dialog, cmd_msg),
			SipTransaction::NoN => no_tran::handle_command_msg(dialog, cmd_msg),
		}
	}
	///处理事务结束的操作..
	/// 这里的参数借用SipTimeControl.Finish:正常结束.Overtime:超时结束..其他都是存在异常的结束
	/// 返回true表示是否发送结束dialog消息.
	pub fn end_tran(&self, dialog: &mut Dialog) -> ResultEx<bool> {
		match self {
			SipTransaction::InviteClient => inv_client::end_tran(dialog),
			SipTransaction::NonInviteClient => non_inv_client::end_tran(dialog),
			SipTransaction::InviteServer => inv_server::end_tran(dialog),
			SipTransaction::NonInviteServer => non_inv_server::end_tran(dialog),
			SipTransaction::NoN => no_tran::end_tran(dialog),
		}
	}

	///计算此事务超时的时间.如果返回Zero代表不存在超时时间.
	pub fn timeout_period(&self, dialog: &mut Dialog) -> SipTimeOver {
		match (dialog.over_time, dialog.is_unsafe_protocol()) {
			(SipTimeOver::TranOvertime(m), true) | (SipTimeOver::CallOvertime(m), true) => {
				if m == Duration::ZERO {
					return SipTimeOver::Zero;
				}
				
				let tmp = get_now_duration() - dialog.start_time;
				let o_t = if m < tmp { Duration::ZERO } else { m - tmp };

				if dialog.retry_time.is_zero() {
					return dialog.over_time.merge(o_t);
				}

				if dialog.retry_time < o_t {
					let time  = dialog.retry_time;
					dialog.retry_time *= 2;

					SipTimeOver::Retry(MAX_TRY_TIME.min(time))
				} else {
					dialog.over_time.merge(o_t)
				}
			}
			(SipTimeOver::CallOvertime(m), false)
			| (SipTimeOver::TranOvertime(m), false)
			| (SipTimeOver::Finish(m), _) => {
				let tmp = get_now_duration() - dialog.start_time;
				let o_t = if m < tmp { Duration::ZERO } else { m - tmp };

				dialog.over_time.merge(o_t)
			}	

			(SipTimeOver::Retry(d), _) => {
				error!("ct里面不应该放retry这个值.");
				SipTimeOver::Retry(d)
			}
			(SipTimeOver::Zero, _) => SipTimeOver::Zero,
		}
	}

	///处理超时的方法
	pub fn handle_time_over(&self, dialog: &mut Dialog, to: SipTimeOver) -> ResultNull {
		match self {
			SipTransaction::InviteClient => inv_client::handle_time_over(dialog, to),
			SipTransaction::NonInviteClient => non_inv_client::handle_time_over(dialog, to),
			SipTransaction::InviteServer => inv_server::handle_time_over(dialog, to),
			SipTransaction::NonInviteServer => non_inv_server::handle_time_over(dialog, to),
			SipTransaction::NoN => no_tran::handle_time_over(dialog, to),
		}
	}
}

///事务状态
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
pub(crate) enum SipTransactionState {
	Callin,
	Trying,
	Proceeding,
	Completed,
	Confirmed,
	Terminated,
}

impl Default for SipTransactionState {
	fn default() -> Self {
		Self::Trying
	}
}

///正在等待回复的某个消息类型
#[derive(Debug, PartialEq, Eq)]
pub(crate) enum WaitSipMessage {
	///对应发送200以后收到Ack消息
	DilaogVerify,
	///对应invite时300-699消息后面的Ack消息
	AckOther,
	///对应200
	Ok,
	///可能收到成功,或者收到失败
	SuccessOrFailure,
	None,
}

///发送等待响应的包.
/// 同时设置重发消息各项配置
#[inline]
pub fn send_wait_resp(dialog: &mut Dialog, send_method: WaitSipMessage, buf: Bytes) {
	dialog.retry_time = T1;
	dialog.wait_resp_method = send_method;
	dialog.send_to_remote(buf);
}

///sip处理的时候的超时控制.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
pub(crate) enum SipTimeOver {
	///事务的超时结束
	TranOvertime(Duration),
	Finish(Duration),
	///呼叫过程当中的超时,
	CallOvertime(Duration),
	///需要进行重发
	Retry(Duration),
	Zero,
}

impl SipTimeOver {
	pub fn merge(&self, d: Duration) -> Self {
		match self {
			SipTimeOver::Retry(_) => SipTimeOver::Retry(d),
			SipTimeOver::CallOvertime(_) => SipTimeOver::CallOvertime(d),
			SipTimeOver::Finish(_) => SipTimeOver::Finish(d),
			SipTimeOver::TranOvertime(_) => SipTimeOver::TranOvertime(d),
			SipTimeOver::Zero => SipTimeOver::Zero,
		}
	}

	pub fn time(&self) -> Duration {
		match self {
			SipTimeOver::Retry(t) => t.clone(),
			SipTimeOver::Zero => Duration::ZERO,
			SipTimeOver::CallOvertime(t) => t.clone(),
			SipTimeOver::Finish(t) => t.clone(),
			SipTimeOver::TranOvertime(t) => t.clone(),
		}
	}
}
